﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Services.Client;
using YourWorld.Common.GreenWorldEntitiesService;
using BusinessObjects;
using System.Collections.ObjectModel;

namespace MainGameModule.Models
{
    public class RegionObjectsRepository
    {
        private const string ServiceUrl = @"http://48de1d712dd7438f8e308ea3b1e69aae.cloudapp.net/GreenWorldDataService.svc";
        private GreenWorldEntities entities;

        private ObservableCollection<Event> eventsList;
        private static RegionObjectsRepository instance;

        public event Action Loaded;

        private RegionObjectsRepository()
        {
            this.RegionObjects = new Dictionary<int, RegionObject>();
            this.entities = new GreenWorldEntities( new Uri( ServiceUrl, UriKind.RelativeOrAbsolute ) );
        }

        public static RegionObjectsRepository Instance
        {
            get
            {
                if ( instance == null )
                    instance = new RegionObjectsRepository();

                return instance;
            }
        }

        public Dictionary<int, RegionObject> RegionObjects
        {
            get;
            private set;
        }

        public ObservableCollection<Event> EventsList
        {
            get
            {
                if ( this.eventsList == null )
                    this.eventsList = new ObservableCollection<Event>();

                return this.eventsList;
            }
            set
            {
                if ( this.eventsList == value )
                    return;

                this.eventsList = value;
            }
        }

        public void Initialize()
        {
            this.LoadRegionObjects();
        }

        public RegionObject GetRegionObject( int id )
        {
            if ( this.RegionObjects.ContainsKey( id ) == false )
                throw new ArgumentException( "Region object with Id = " + id + " is not available!" );

            return this.RegionObjects[id];
        }

        public Event GetQuest( int id )
        {
            Event quest = this.EventsList.Where( x => x.Id == id ).FirstOrDefault();
            if ( quest == null )
                throw new ArgumentException( "Quest with Id = " + id + " is not available!" );

            return quest.Clone() as Event;
        }

        private void LoadRegionObjects()
        {
            var regionObjects = ( from r in entities.RegionObjects select r ) as DataServiceQuery<RegionObject>;
            regionObjects.BeginExecute( new AsyncCallback( this.LoadRegionObjectsCompleted ), regionObjects );
        }

        private void LoadRegionObjectsCompleted( IAsyncResult state )
        {
            var regionObjects = state.AsyncState as DataServiceQuery<RegionObject>;

            List<RegionObject> ros = regionObjects.EndExecute( state ).ToList();
            List<string> badgeIds;

            foreach ( RegionObject ro in ros )
            {
                this.RegionObjects.Add( ro.Id, ro );

                RegionObjectTypes type;
                if ( Enum.TryParse<RegionObjectTypes>( ro.Template, true, out type ) == false )
                    type = RegionObjectTypes.Build;

                if ( type == RegionObjectTypes.Causes || type == RegionObjectTypes.Build )
                {
                    Event userEvent = new Event()
                    {
                        Id = ro.Id,
                        Image = ro.Image,
                        IsLocked = true,
                        Type = type,
                        Description = ro.Description,
                        Title = ro.Title,
                        RequiredMembersCount = ro.RequiredMembersCount ?? 0,
                        IsBuild = type == RegionObjectTypes.Build
                    };

                    if ( ro.RequiresBadges != null )
                    {
                        badgeIds = ro.RequiresBadges.Split( new string[] { "," }, StringSplitOptions.RemoveEmptyEntries ).ToList();

                        foreach ( string badgeId in badgeIds )
                        {
                            int id = Int32.Parse( badgeId );
                            userEvent.RequiredBadgesIds.Add( id );
                            userEvent.RequiredBadges.Add( BadgesRepository.Instance.GetBadge( id ) );
                        }
                    }

                    if ( type == RegionObjectTypes.Build )
                        this.EventsList.Insert( 0, userEvent );
                    else
                        this.EventsList.Add( userEvent );
                }
            }

            if ( this.Loaded != null )
                this.Loaded();
        }
    }
}
